home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / SOURCE / LIBPNG / PNGREAD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-24  |  22.2 KB  |  691 lines  |  [TEXT/CWIE]

  1.  
  2. /* pngread.c - read a png file
  3.  
  4.    libpng 1.0 beta 4 - version 0.90
  5.    For conditions of distribution and use, see copyright notice in png.h
  6.    Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  7.    January 10, 1997
  8.    */
  9.  
  10. #define PNG_INTERNAL
  11. #include "png.h"
  12.  
  13. /* Create a png structure for reading, and allocate any memory needed. */
  14. png_structp
  15. png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr,
  16.    png_error_ptr error_fn, png_error_ptr warn_fn)
  17. {
  18.    png_structp png_ptr;
  19. #ifdef USE_FAR_KEYWORD
  20.    jmp_buf jmpbuf;
  21. #endif
  22.    if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
  23.    {
  24.       return (png_structp)NULL;
  25.    }
  26. #ifdef USE_FAR_KEYWORD
  27.    if (setjmp(jmpbuf))
  28. #else
  29.    if (setjmp(png_ptr->jmpbuf))
  30. #endif
  31.    {
  32.       png_free(png_ptr, png_ptr->zbuf);
  33.       png_destroy_struct(png_ptr);
  34.       return (png_structp)NULL;
  35.    }
  36. #ifdef USE_FAR_KEYWORD
  37.    png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
  38. #endif
  39.    png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
  40.  
  41.    /* This is what will be used for the final version.  For the
  42.       (ongoing) development library, we know that ALL of the
  43.       older library versions are out of date because of the
  44.       change in the info_struct size. */
  45.    if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0])
  46.    {
  47.       png_error(png_ptr,
  48.                 "Incompatible libpng version in application and library");
  49.    }
  50.  
  51.    /* initialize zbuf - compression buffer */
  52.    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
  53.    png_ptr->zbuf = png_malloc(png_ptr, png_ptr->zbuf_size);
  54.    png_ptr->zstream.zalloc = png_zalloc;
  55.    png_ptr->zstream.zfree = png_zfree;
  56.    png_ptr->zstream.opaque = (voidpf)png_ptr;
  57.  
  58.    switch (inflateInit(&png_ptr->zstream))
  59.    {
  60.      case Z_OK: /* Do nothing */ break;
  61.      case Z_MEM_ERROR:
  62.      case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break;
  63.      case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break;
  64.      default: png_error(png_ptr, "Unknown zlib error");
  65.    }
  66.  
  67.    png_ptr->zstream.next_out = png_ptr->zbuf;
  68.    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
  69.  
  70.    png_set_read_fn(png_ptr, NULL, NULL);
  71.  
  72.    return (png_ptr);
  73. }
  74.  
  75.  
  76. /* Initialize png structure for reading, and allocate any memory needed.
  77.    This interface is depreciated in favour of the png_create_read_struct(),
  78.    and it will eventually disappear. */
  79. void
  80. png_read_init(png_structp png_ptr)
  81. {
  82.    jmp_buf tmp_jmp;  /* to save current jump buffer */
  83.  
  84.    /* save jump buffer and error functions */
  85.    png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
  86.  
  87.    /* reset all variables to 0 */
  88.    png_memset(png_ptr, 0, sizeof (png_struct));
  89.  
  90.    /* restore jump buffer */
  91.    png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
  92.  
  93.    /* initialize zbuf - compression buffer */
  94.    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
  95.    png_ptr->zbuf = png_malloc(png_ptr, png_ptr->zbuf_size);
  96.    png_ptr->zstream.zalloc = png_zalloc;
  97.    png_ptr->zstream.zfree = png_zfree;
  98.    png_ptr->zstream.opaque = (voidpf)png_ptr;
  99.  
  100.    switch (inflateInit(&png_ptr->zstream))
  101.    {
  102.      case Z_OK: /* Do nothing */ break;
  103.      case Z_MEM_ERROR:
  104.      case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break;
  105.      case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break;
  106.      default: png_error(png_ptr, "Unknown zlib error");
  107.    }
  108.  
  109.    png_ptr->zstream.next_out = png_ptr->zbuf;
  110.    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
  111.  
  112.    png_set_read_fn(png_ptr, NULL, NULL);
  113. }
  114.  
  115. /* Read the information before the actual image data.  This has been
  116.  * changed in v0.90 to allow reading a file which already has the magic
  117.  * bytes read from the stream.  You can tell libpng how many bytes have
  118.  * been read from the beginning of the stream (up to the maxumum of 8)
  119.  * via png_set_sig_bytes(), and we will only check the remaining bytes
  120.  * here.  The application can then have access to the signature bytes we
  121.  * read if it is determined that this isn't a valid PNG file.
  122.  */
  123. void
  124. png_read_info(png_structp png_ptr, png_infop info_ptr)
  125. {
  126.    /* If we haven't checked all of the PNG signature bytes, do so now. */
  127.    if (png_ptr->sig_bytes < 8)
  128.    {
  129.       int num_checked = png_ptr->sig_bytes,
  130.           num_to_check = 8 - num_checked;
  131.  
  132.       png_read_data(png_ptr, &(info_ptr->signature[num_checked]), 
  133.          (png_uint_32)num_to_check);
  134.       png_ptr->sig_bytes = 8;
  135.  
  136.       if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
  137.       {
  138.          if (num_checked < 4 &&
  139.              png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
  140.             png_error(png_ptr, "Not a PNG file");
  141.          else
  142.             png_error(png_ptr, "PNG file corrupted by ASCII conversion");
  143.       }
  144.    }
  145.  
  146.    while (1)
  147.    {
  148.       png_byte chunk_length[4];
  149.       png_uint_32 length;
  150.  
  151.       png_read_data(png_ptr, chunk_length, 4);
  152.       length = png_get_uint_32(chunk_length);
  153.  
  154.       png_reset_crc(png_ptr);
  155.       png_crc_read(png_ptr, png_ptr->chunk_name, 4);
  156.  
  157.       if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
  158.          png_handle_IHDR(png_ptr, info_ptr, length);
  159.       else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
  160.          png_handle_PLTE(png_ptr, info_ptr, length);
  161.       else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
  162.          png_handle_IEND(png_ptr, info_ptr, length);
  163. #if defined(PNG_READ_gAMA_SUPPORTED)
  164.       else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
  165.          png_handle_gAMA(png_ptr, info_ptr, length);
  166. #endif
  167. #if defined(PNG_READ_sBIT_SUPPORTED)
  168.       else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
  169.          png_handle_sBIT(png_ptr, info_ptr, length);
  170. #endif
  171. #if defined(PNG_READ_cHRM_SUPPORTED)
  172.       else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
  173.          png_handle_cHRM(png_ptr, info_ptr, length);
  174. #endif
  175. #if defined(PNG_READ_tRNS_SUPPORTED)
  176.       else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
  177.          png_handle_tRNS(png_ptr, info_ptr, length);
  178. #endif
  179. #if defined(PNG_READ_bKGD_SUPPORTED)
  180.       else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
  181.          png_handle_bKGD(png_ptr, info_ptr, length);
  182. #endif
  183. #if defined(PNG_READ_hIST_SUPPORTED)
  184.       else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
  185.          png_handle_hIST(png_ptr, info_ptr, length);
  186. #endif
  187. #if defined(PNG_READ_pHYs_SUPPORTED)
  188.       else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
  189.          png_handle_pHYs(png_ptr, info_ptr, length);
  190. #endif
  191. #if defined(PNG_READ_oFFs_SUPPORTED)
  192.       else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
  193.          png_handle_oFFs(png_ptr, info_ptr, length);
  194. #endif
  195. #if defined(PNG_READ_tIME_SUPPORTED)
  196.       else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
  197.          png_handle_tIME(png_ptr, info_ptr, length);
  198. #endif
  199. #if defined(PNG_READ_tEXt_SUPPORTED)
  200.       else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
  201.          png_handle_tEXt(png_ptr, info_ptr, length);
  202. #endif
  203. #if defined(PNG_READ_zTXt_SUPPORTED)
  204.       else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
  205.          png_handle_zTXt(png_ptr, info_ptr, length);
  206. #endif
  207.       else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
  208.       {
  209.          if (!(png_ptr->mode & PNG_HAVE_IHDR))
  210.             png_error(png_ptr, "Missing IHDR before IDAT");
  211.          else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
  212.                   !(png_ptr->mode & PNG_HAVE_PLTE))
  213.             png_error(png_ptr, "Missing PLTE before IDAT");
  214.  
  215.          png_ptr->idat_size = length;
  216.          png_ptr->mode |= PNG_HAVE_IDAT;
  217.          break;
  218.       }
  219.       else
  220.          png_handle_unknown(png_ptr, info_ptr, length);
  221.    }
  222. }
  223.  
  224. /* optional call to update the users info_ptr structure */
  225. void
  226. png_read_update_info(png_structp png_ptr, png_infop info_ptr)
  227. {
  228.    if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
  229.       png_read_start_row(png_ptr);
  230.    png_read_transform_info(png_ptr, info_ptr);
  231. }
  232.  
  233. /* initialize palette, background, etc, after transformations
  234.    are set, but before any reading takes place.  This allows
  235.    the user to obtail a gamma corrected palette, for example.
  236.    If the user doesn't call this, we will do it ourselves. */
  237. void
  238. png_start_read_image(png_structp png_ptr)
  239. {
  240.    if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
  241.       png_read_start_row(png_ptr);
  242. }
  243.  
  244. void
  245. png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
  246. {
  247.    int ret;
  248.    if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
  249.       png_read_start_row(png_ptr);
  250.  
  251. #if defined(PNG_READ_INTERLACING_SUPPORTED)
  252.    /* if interlaced and we do not need a new row, combine row and return */
  253.    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
  254.    {
  255.       switch (png_ptr->pass)
  256.       {
  257.          case 0:
  258.             if (png_ptr->row_number & 7)
  259.             {
  260.                if (dsp_row)
  261.                   png_combine_row(png_ptr, dsp_row,
  262.                      png_pass_dsp_mask[png_ptr->pass]);
  263.                png_read_finish_row(png_ptr);
  264.                return;
  265.             }
  266.             break;
  267.          case 1:
  268.             if ((png_ptr->row_number & 7) || png_ptr->width < 5)
  269.             {
  270.                if (dsp_row)
  271.                   png_combine_row(png_ptr, dsp_row,
  272.                      png_pass_dsp_mask[png_ptr->pass]);
  273.                png_read_finish_row(png_ptr);
  274.                return;
  275.             }
  276.             break;
  277.          case 2:
  278.             if ((png_ptr->row_number & 7) != 4)
  279.             {
  280.                if (dsp_row && (png_ptr->row_number & 4))
  281.                   png_combine_row(png_ptr, dsp_row,
  282.                      png_pass_dsp_mask[png_ptr->pass]);
  283.                png_read_finish_row(png_ptr);
  284.                return;
  285.             }
  286.             break;
  287.          case 3:
  288.             if ((png_ptr->row_number & 3) || png_ptr->width < 3)
  289.             {
  290.                if (dsp_row)
  291.                   png_combine_row(png_ptr, dsp_row,
  292.                      png_pass_dsp_mask[png_ptr->pass]);
  293.                png_read_finish_row(png_ptr);
  294.                return;
  295.             }
  296.             break;
  297.          case 4:
  298.             if ((png_ptr->row_number & 3) != 2)
  299.             {
  300.                if (dsp_row && (png_ptr->row_number & 2))
  301.                   png_combine_row(png_ptr, dsp_row,
  302.                      png_pass_dsp_mask[png_ptr->pass]);
  303.                png_read_finish_row(png_ptr);
  304.                return;
  305.             }
  306.             break;
  307.          case 5:
  308.             if ((png_ptr->row_number & 1) || png_ptr->width < 2)
  309.             {
  310.                if (dsp_row)
  311.                   png_combine_row(png_ptr, dsp_row,
  312.                      png_pass_dsp_mask[png_ptr->pass]);
  313.                png_read_finish_row(png_ptr);
  314.                return;
  315.             }
  316.             break;
  317.          case 6:
  318.             if (!(png_ptr->row_number & 1))
  319.             {
  320.                png_read_finish_row(png_ptr);
  321.                return;
  322.             }
  323.             break;
  324.       }
  325.    }
  326. #endif
  327.  
  328.    if (!(png_ptr->mode & PNG_HAVE_IDAT))
  329.       png_error(png_ptr, "Invalid attempt to read row data");
  330.  
  331.    png_ptr->zstream.next_out = png_ptr->row_buf;
  332.    png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
  333.    do
  334.    {
  335.       if (!(png_ptr->zstream.avail_in))
  336.       {
  337.          while (!png_ptr->idat_size)
  338.          {
  339.             png_byte chunk_length[4];
  340.  
  341.             png_crc_finish(png_ptr, 0);
  342.  
  343.             png_read_data(png_ptr, chunk_length, 4);
  344.             png_ptr->idat_size = png_get_uint_32(chunk_length);
  345.  
  346.             png_reset_crc(png_ptr);
  347.             png_crc_read(png_ptr, png_ptr->chunk_name, 4);
  348.             if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
  349.                png_error(png_ptr, "Not enough image data");
  350.          }
  351.          png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
  352.          png_ptr->zstream.next_in = png_ptr->zbuf;
  353.          if (png_ptr->zbuf_size > png_ptr->idat_size)
  354.             png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
  355.          png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
  356.          png_ptr->idat_size -= png_ptr->zstream.avail_in;
  357.       }
  358.       ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
  359.       if (ret == Z_STREAM_END)
  360.       {
  361.          if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in ||
  362.             png_ptr->idat_size)
  363.             png_error(png_ptr, "Extra compressed data");
  364.          png_ptr->mode |= PNG_AFTER_IDAT;
  365.          png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
  366.          break;
  367.       }
  368.       if (ret != Z_OK)
  369.          png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
  370.                    "Decompression error");
  371.  
  372.    } while (png_ptr->zstream.avail_out);
  373.  
  374.    png_ptr->row_info.color_type = png_ptr->color_type;
  375.    png_ptr->row_info.width = png_ptr->iwidth;
  376.    png_ptr->row_info.channels = png_ptr->channels;
  377.    png_ptr->row_info.bit_depth = png_ptr->bit_depth;
  378.    png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
  379.    png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
  380.       (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
  381.  
  382.    png_read_filter_row(png_ptr, &(png_ptr->row_info),
  383.       png_ptr->row_buf + 1, png_ptr->prev_row + 1,
  384.       (int)(png_ptr->row_buf[0]));
  385.  
  386.    png_memcpy(png_ptr->prev_row, png_ptr->row_buf, (png_size_t)png_ptr->rowbytes + 1);
  387.  
  388.    if (png_ptr->transformations)
  389.       png_do_read_transformations(png_ptr);
  390.  
  391. #if defined(PNG_READ_INTERLACING_SUPPORTED)
  392.    /* blow up interlaced rows to full size */
  393.    if (png_ptr->interlaced &&
  394.       (png_ptr->transformations & PNG_INTERLACE))
  395.    {
  396.       if (png_ptr->pass < 6)
  397.          png_do_read_interlace(&(png_ptr->row_info),
  398.             png_ptr->row_buf + 1, png_ptr->pass);
  399.  
  400.       if (dsp_row)
  401.          png_combine_row(png_ptr, dsp_row,
  402.             png_pass_dsp_mask[png_ptr->pass]);
  403.       if (row)
  404.          png_combine_row(png_ptr, row,
  405.             png_pass_mask[png_ptr->pass]);
  406.    }
  407.    else
  408. #endif
  409.    {
  410.       if (row)
  411.          png_combine_row(png_ptr, row, 0xff);
  412.       if (dsp_row)
  413.          png_combine_row(png_ptr, dsp_row, 0xff);
  414.    }
  415.    png_read_finish_row(png_ptr);
  416. }
  417.  
  418. /* read a one or more rows of image data.   If the image is interlaced,
  419.    and png_set_interlace_handling() has been called, the rows need to
  420.    to contain the contents of the rows from the previous pass.  If
  421.    the image has alpha or transparency, and png_handle_alpha() has been
  422.    called, the rows contents must be initialized to the contents of the
  423.    screen.  row holds the actual image, and pixels are placed in it
  424.    as they arrive.  If the image is displayed after each pass, it will
  425.    appear to "sparkle" in.  display_row can be used to display a
  426.    "chunky" progressive image, with finer detail added as it becomes
  427.    available.  If you do not want this "chunky" display, you may pass
  428.    NULL for display_rows.  If you do not want the sparkle display, and
  429.    you have not called png_handle_alpha(), you may pass NULL for rows.
  430.    If you have called png_handle_alpha(), and the image has either an
  431.    alpha channel or a transparency chunk, you must provide a buffer for
  432.    rows.  In this case, you do not have to provide a display_rows buffer
  433.    also, but you may.  If the image is not interlaced, or if you have
  434.    not called png_set_interlace_handling(), the display_row buffer will
  435.    be ignored, so pass NULL to it. */
  436.  
  437. void
  438. png_read_rows(png_structp png_ptr, png_bytepp row,
  439.    png_bytepp display_row, png_uint_32 num_rows)
  440. {
  441.    png_uint_32 i;
  442.    png_bytepp rp;
  443.    png_bytepp dp;
  444.  
  445.    rp = row;
  446.    dp = display_row;
  447.    for (i = 0; i < num_rows; i++)
  448.    {
  449.       png_bytep rptr;
  450.       png_bytep dptr;
  451.  
  452.       if (rp)
  453.          rptr = *rp;
  454.       else
  455.          rptr = NULL;
  456.       if (dp)
  457.          dptr = *dp;
  458.       else
  459.          dptr = NULL;
  460.       png_read_row(png_ptr, rptr, dptr);
  461.       if (row)
  462.          rp++;
  463.       if (display_row)
  464.          dp++;
  465.    }
  466. }
  467.  
  468. /* read the image.  If the image has an alpha channel or a transparency
  469.    chunk, and you have called png_handle_alpha(), you will need to
  470.    initialize the image to the current image that png will be overlaying.
  471.    We set the num_rows again here, in case it was incorrectly set in
  472.    png_read_start_row() by a call to png_read_update_info() or
  473.    png_start_read_image() if png_set_interlace_handling() wasn't called
  474.    prior to either of these functions like it should have been.  You only
  475.    need to call this function once.  If you desire to have an image for
  476.    each pass of a interlaced image, use png_read_rows() instead */
  477. void
  478. png_read_image(png_structp png_ptr, png_bytepp image)
  479. {
  480.    png_uint_32 i;
  481.    int pass, j;
  482.    png_bytepp rp;
  483.  
  484.    pass = png_set_interlace_handling(png_ptr);
  485.  
  486.    png_ptr->num_rows = png_ptr->height; /* Make sure this is set correctly */
  487.  
  488.    for (j = 0; j < pass; j++)
  489.    {
  490.       rp = image;
  491.       for (i = 0; i < png_ptr->height; i++)
  492.       {
  493.          png_read_row(png_ptr, *rp, NULL);
  494.          rp++;
  495.       }
  496.    }
  497. }
  498.  
  499. /* read the end of the png file.  Will not read past the end of the
  500.    file, will verify the end is accurate, and will read any comments
  501.    or time information at the end of the file, if info is not NULL. */
  502. void
  503. png_read_end(png_structp png_ptr, png_infop info_ptr)
  504. {
  505.    png_byte chunk_length[4];
  506.    png_uint_32 length;
  507.  
  508.    png_crc_finish(png_ptr, 0);
  509.  
  510.    do
  511.    {
  512.       png_read_data(png_ptr, chunk_length, 4);
  513.       length = png_get_uint_32(chunk_length);
  514.  
  515.       png_reset_crc(png_ptr);
  516.       png_crc_read(png_ptr, png_ptr->chunk_name, 4);
  517.  
  518.       if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
  519.          png_handle_IHDR(png_ptr, info_ptr, length);
  520.       else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
  521.          png_handle_PLTE(png_ptr, info_ptr, length);
  522.       else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
  523.          png_handle_gAMA(png_ptr, info_ptr, length);
  524.       else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
  525.          png_handle_sBIT(png_ptr, info_ptr, length);
  526.       else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
  527.          png_handle_cHRM(png_ptr, info_ptr, length);
  528.       else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
  529.          png_handle_tRNS(png_ptr, info_ptr, length);
  530.       else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
  531.          png_handle_bKGD(png_ptr, info_ptr, length);
  532.       else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
  533.          png_handle_hIST(png_ptr, info_ptr, length);
  534.       else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
  535.          png_handle_pHYs(png_ptr, info_ptr, length);
  536.       else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
  537.          png_handle_oFFs(png_ptr, info_ptr, length);
  538.       else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
  539.       {
  540.          if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT)
  541.             png_error(png_ptr, "Too many IDAT's found");
  542.       }
  543. #if defined(PNG_READ_tIME_SUPPORTED)
  544.       else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
  545.          png_handle_tIME(png_ptr, info_ptr, length);
  546. #endif
  547. #if defined(PNG_READ_tEXt_SUPPORTED)
  548.       else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
  549.          png_handle_tEXt(png_ptr, info_ptr, length);
  550. #endif
  551. #if defined(PNG_READ_zTXt_SUPPORTED)
  552.       else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
  553.          png_handle_zTXt(png_ptr, info_ptr, length);
  554. #endif
  555.       else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
  556.          png_handle_IEND(png_ptr, info_ptr, length);
  557.       else
  558.          png_handle_unknown(png_ptr, info_ptr, length);
  559.    } while (!(png_ptr->mode & PNG_HAVE_IEND));
  560. }
  561.  
  562. /* free all memory used by the read */
  563. void
  564. png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
  565.    png_infopp end_info_ptr_ptr)
  566. {
  567.    png_structp png_ptr = NULL;
  568.    png_infop info_ptr = NULL, end_info_ptr = NULL;
  569.  
  570.    if (png_ptr_ptr)
  571.       png_ptr = *png_ptr_ptr;
  572.  
  573.    if (info_ptr_ptr)
  574.       info_ptr = *info_ptr_ptr;
  575.  
  576.    if (end_info_ptr_ptr)
  577.       end_info_ptr = *end_info_ptr_ptr;
  578.  
  579.    png_read_destroy(png_ptr, info_ptr, end_info_ptr);
  580.  
  581.    if (info_ptr)
  582.    {
  583.       png_destroy_struct((png_voidp)info_ptr);
  584.       *info_ptr_ptr = (png_infop)NULL;
  585.    }
  586.  
  587.    if (end_info_ptr)
  588.    {
  589.       png_destroy_struct((png_voidp)end_info_ptr);
  590.       *end_info_ptr_ptr = (png_infop)NULL;
  591.    }
  592.  
  593.    if (png_ptr)
  594.    {
  595.       png_destroy_struct((png_voidp)png_ptr);
  596.       *png_ptr_ptr = (png_structp)NULL;
  597.    }
  598. }
  599.  
  600. /* free all memory used by the read (old method) */
  601. void
  602. png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr)
  603. {
  604.    int i;
  605.    jmp_buf tmp_jmp;
  606.    png_error_ptr error_fn;
  607.    png_error_ptr warning_fn;
  608.    png_voidp error_ptr;
  609.  
  610.    if (info_ptr)
  611.       png_info_destroy(png_ptr, info_ptr);
  612.  
  613.    if (end_info_ptr)
  614.       png_info_destroy(png_ptr, end_info_ptr);
  615.  
  616.    png_free(png_ptr, png_ptr->zbuf);
  617.    png_free(png_ptr, png_ptr->row_buf);
  618.    png_free(png_ptr, png_ptr->prev_row);
  619. #if defined(PNG_READ_DITHER_SUPPORTED)
  620.    png_free(png_ptr, png_ptr->palette_lookup);
  621.    png_free(png_ptr, png_ptr->dither_index);
  622. #endif
  623. #if defined(PNG_READ_GAMMA_SUPPORTED)
  624.    png_free(png_ptr, png_ptr->gamma_table);
  625. #endif
  626. #if defined(PNG_READ_BACKGROUND_SUPPORTED)
  627.    png_free(png_ptr, png_ptr->gamma_from_1);
  628.    png_free(png_ptr, png_ptr->gamma_to_1);
  629. #endif
  630.    if (png_ptr->flags & PNG_FLAG_FREE_PALETTE)
  631.       png_free(png_ptr, png_ptr->palette);
  632. #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_bKGD_SUPPORTED)
  633.    if (png_ptr->flags & PNG_FLAG_FREE_TRANS)
  634.       png_free(png_ptr, png_ptr->trans);
  635. #endif
  636. #if defined(PNG_READ_hIST_SUPPORTED)
  637.    if (png_ptr->flags & PNG_FLAG_FREE_HIST)
  638.       png_free(png_ptr, png_ptr->hist);
  639. #endif
  640. #if defined(PNG_READ_GAMMA_SUPPORTED)
  641.    if (png_ptr->gamma_16_table)
  642.    {
  643.       for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
  644.       {
  645.          png_free(png_ptr, png_ptr->gamma_16_table[i]);
  646.       }
  647.    }
  648. #endif
  649. #if defined(PNG_READ_BACKGROUND_SUPPORTED)
  650.    png_free(png_ptr, png_ptr->gamma_16_table);
  651.    if (png_ptr->gamma_16_from_1)
  652.    {
  653.       for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
  654.       {
  655.          png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
  656.       }
  657.    }
  658.    png_free(png_ptr, png_ptr->gamma_16_from_1);
  659.    if (png_ptr->gamma_16_to_1)
  660.    {
  661.       for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
  662.       {
  663.          png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
  664.       }
  665.    }
  666.    png_free(png_ptr, png_ptr->gamma_16_to_1);
  667. #endif
  668.  
  669.    inflateEnd(&png_ptr->zstream);
  670. #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
  671.    png_free(png_ptr, png_ptr->save_buffer);
  672. #endif
  673.  
  674.    /* Save the important info out of the png_struct, in case it is
  675.     * being used again.
  676.     */
  677.    png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
  678.  
  679.    error_fn = png_ptr->error_fn;
  680.    warning_fn = png_ptr->warning_fn;
  681.    error_ptr = png_ptr->error_ptr;
  682.  
  683.    png_memset(png_ptr, 0, sizeof (png_struct));
  684.  
  685.    png_ptr->error_fn = error_fn;
  686.    png_ptr->warning_fn = warning_fn;
  687.    png_ptr->error_ptr = error_ptr;
  688.  
  689.    png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
  690. }
  691.